package cn.growthgate.fgo.util;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;

import cn.growthgate.fgo.core.shiro.ShiroDbRealm;
import cn.growthgate.fgo.core.shiro.SimpleUser;
import cn.growthgate.fgo.entity.User;
import cn.growthgate.fgo.entity.enums.Role;
import cn.growthgate.fgo.service.IUserService;

/**
 * 用户认证工具类
 * 
 * @author GrowthGate
 * @since 2019年1月23日
 *
 */
public class AuthenticationUtils {
	
	public static final String DEFAULT_LOGIN_URL = "/login";
	public static final String DEFAULT_SUCCESS_URL = "/";
	public static final String DEFAULT_UNAUTHORIZED_URL = "/login";

	public static Subject getSubject() {
		Subject subject = null;
		try {
			subject = SecurityUtils.getSubject();
		} catch (UnavailableSecurityManagerException e) {
		}
		return subject;
	}
	
	public static SecurityManager getSecurityManager() {
		return SecurityUtils.getSecurityManager();
	}

	/**
	 * 登录
	 * @param request
	 */
	public static void doLogin(User user, boolean rememberMe) {
		UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), rememberMe);
		Subject subject = getSubject();
		ThreadContext.bind(subject);
		// 进行用户名和密码验证
		subject.login(token);
	}
	
	/**
	 * 登出
	 */
	public static void doLogout() {
		getSubject().logout();
	}
	
	/**
	 * 判断当前用户是否拥有列表中的一个或多个角色
	 * @param roles
	 * @return
	 */
	public static boolean hasAnyRoles(Role... roles) {
		if (roles == null) {
			return false;
		}
		String[] roleNames = new String[roles.length];
		for (int i = 0; i < roles.length; i++) {
			roleNames[i] = roles[i].getName();
		}
		return hasAnyRoles(roleNames);
	}
	
	/**
	 * 判断当前用户是否拥有列表中的一个或多个角色
	 * @param roles
	 * @return
	 */
	public static boolean hasAnyRoles(List<String> roles) {
		return hasAnyRoles(CollectionUtils.toArray(roles, String.class));
	}
	
	/**
	 * 判断当前用户是否拥有列表中的一个或多个角色
	 * @param roles
	 * @return
	 */
	public static boolean hasAnyRoles(String... roleNames) {
		Subject subject = getSubject();
		boolean ret = true && subject != null && roleNames != null && roleNames.length > 0;
		if (!ret) {
			return false;
		}
		for (String role : roleNames) {
			if (subject.hasRole(role.trim())) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 获取当前登录的用户信息
	 * @return
	 */
	public static SimpleUser getLoginSimpleUser() {
		return getSubject() != null ? (SimpleUser) getSubject().getPrincipal() : null;
	}
	
	/**
	 * 获取当前登录的用户对象
	 * @return
	 */
	public static User getLoginUser() {
		IUserService userService = SpringUtils.getBean(IUserService.class);
		SimpleUser simpleUser = getLoginSimpleUser();
		return simpleUser != null ? userService.selectById(simpleUser.getId()) : null;
	}
	
	/**
	 * 获取当前登录的用户id
	 * @return
	 */
	public static Long getLoginUserId() {
		SimpleUser simpleUser = getLoginSimpleUser();
		return simpleUser != null ? simpleUser.getId() : null;
	}
	
	/**
	 * 获取当前登录主机ip
	 * @return
	 */
	public static String getLoginHost() {
		return getSubject().getSession().getHost();
	}
	
	/**
	 * 判断当前用户是否为已登录用户
	 * @return
	 */
	public static boolean isAuthenticated() {
		return getSubject() != null && getSubject().isAuthenticated();
	}
	
	/**
	 * 判断当前用户是否为未登录用户
	 * @return
	 */
	public static boolean notAuthenticated() {
		return !isAuthenticated();
	}
	
	/**
	 * 判断当前用户是否为已登录或已记住用户
	 * @return
	 */
	public static boolean isUser() {
		return getSubject() != null && getSubject().getPrincipal() != null;
	}
	
	/**
	 * 判断当前用户是否为未登录且未记住用户
	 * @return
	 */
	public static boolean isGuest() {
		return !isUser();
	}
	
	/**
	 * 更新当前登录用户信息
	 */
	public static void updateLoginSimpleUser() {
		Subject subject = getSubject();
		String realmName = subject.getPrincipals().getRealmNames().iterator().next();
		// 获取更新后的simpleUser
		IUserService userService = SpringUtils.getBean(IUserService.class);
		SimpleUser simpleUser = userService.transformSimpleUser(getLoginUser());
		PrincipalCollection principalCollection = new SimplePrincipalCollection(simpleUser, realmName);
		// 重新加载Principal
		subject.runAs(principalCollection);
	}
	
	/**
	 * 清除用户授权信息缓存
	 * @param user
	 * @return
	 */
	public static void clearCachedAuthorizationInfo(User user) {
		RealmSecurityManager rsm = (RealmSecurityManager) getSecurityManager();
		ShiroDbRealm realm = (ShiroDbRealm) rsm.getRealms().iterator().next();
		realm.clearCachedAuthorizationInfo(user);
	}
	
	/**
	 * 清除全部用户缓存
	 * @return
	 */
	public static void clearAllCachedAuthorizationInfo() {
		RealmSecurityManager rsm = (RealmSecurityManager) getSecurityManager();
		ShiroDbRealm realm = (ShiroDbRealm) rsm.getRealms().iterator().next();
		realm.clearAllCachedAuthorizationInfo();
	}

}
